package com.party.admin.biz.system;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.party.admin.utils.RealmUtils;
import com.party.common.utils.StringUtils;
import com.party.core.model.member.MemberGroup;
import com.party.core.model.menu.Menu;
import com.party.core.model.system.SysPrivilege;
import com.party.core.service.menu.IMenuService;
import com.party.core.service.system.ISysPrivilegeService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


/**
 *菜单业务服务接口
 * Created by wei.li
 *
 * @date 2017/5/19 0019
 * @time 11:42
 */
@Service
public class MenuBizService {

    @Autowired
    private IMenuService menuService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ISysPrivilegeService privilegeService;

    public static final  String ADMIN_MAIN_MENU_ID = "3";

    /**
     * 获取树结构列表
     *
     * @return jsonArray
     */
    public JSONArray getListTree() {
        List<Menu> menus = menuService.listAll();
        List<Map<String, Object>> maps = buildTreeData(menus);
        return JSONArray.parseArray(JSONArray.toJSONString(maps));
    }

    /**
     * 保存
     * @param menu 菜单信息
     * @param permission 权限
     * @return 菜单信息
     */
    @Transactional
    public Menu saveBiz(Menu menu,String permission){
        MemberGroup member = RealmUtils.getCurrentUser();
        if (Strings.isNullOrEmpty(menu.getPrivilegeId())) {
            SysPrivilege sysPrivilege = new SysPrivilege();
            sysPrivilege.setPermission(permission);
            sysPrivilege.setName(menu.getName());
            if (!Strings.isNullOrEmpty(menu.getParentId())) {
                Menu pMenu = menuService.get(menu.getParentId());
                sysPrivilege.setParentId(pMenu.getPrivilegeId());
                sysPrivilege.setSort("0");
            }
            String privilegeId = privilegeService.insert(sysPrivilege);
            menu.setPrivilegeId(privilegeId);
        }else{
            SysPrivilege sysPrivilege = privilegeService.get(menu.getPrivilegeId());
            sysPrivilege.setName(menu.getName());
            sysPrivilege.setPermission(permission);
            privilegeService.update(sysPrivilege);
        }
        if (Strings.isNullOrEmpty(menu.getId())) {
            menu.setCreateBy(member.getId());
            menu.setUpdateBy(member.getId());
            menuService.insert(menu);
        } else {
            menu.setUpdateBy(member.getId());
            menuService.update(menu);
        }
        Menu dbMenu = menuService.get(menu.getId());
        return dbMenu;
    }

    /**
     * 创建管理员数据
     *
     * @return 结果集
     */
    public List<Map> buildAdminData(){
        MemberGroup currentUser = RealmUtils.getCurrentUser();
        String str = (String) redisTemplate.opsForValue().get("myAdminMenuTree_"+currentUser.getId());
        if (!(StringUtils.isEmpty(str) || "[]".equals(str))) {
            return JSONArray.parseArray(str, Map.class);
        }else{
            List<Menu> menus = menuService.listAll();

            // 倒序排列
            Collections.reverse(menus);

            // 权限代码集合
            List<String> permissions = menuService.buildPermission(currentUser.getId(), null);

            List<Map<String, Object>> maps = menuService.buildTreeData(ADMIN_MAIN_MENU_ID, menus, permissions, false);
            String s = JSONArray.toJSONString(maps);
            redisTemplate.opsForValue().set("myAdminMenuTree_"+currentUser.getId(), s);
            return JSONArray.parseArray(s, Map.class);
        }
    }

    /**
     * 创建树形数据
     * @param menus 菜单
     * @return 结果集
     */
    private List<Map<String, Object>> buildTreeData(List<Menu> menus) {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        for(Menu menu:menus){
            HashMap<String, Object> menuMap = Maps.newHashMap();
            menuMap.put("id", menu.getId());
            menuMap.put("pId", menu.getParentId());
            menuMap.put("href", menu.getHref());
            menuMap.put("privilegeId", menu.getPrivilegeId());
            menuMap.put("permission", menu.getPermission());
            menuMap.put("name", menu.getName());
            menuMap.put("rule", menu.getRule());
            menuMap.put("iconfont", menu.getIcon());
            if(null != menu.getParentId() && menu.getParentId().equals("1")){
                menuMap.put("open", true);
            }
            list.add(menuMap);
        }
        return list;
    }

    /**
     * 获取该用户的第一个菜单页面链接
     * @return
     */
    public String firstUrl() {
        String str = (String) redisTemplate.opsForValue().get("myAdminMenuTree_" + RealmUtils.getCurrentUser().getId());
        List<Map> maps = JSONArray.parseArray(str, Map.class);
        return getUrl(maps);
    }

    private Map<String, Object> buildTreeData(String id, List<Menu> menus) {
        HashMap<String, Object> menuMap = Maps.newHashMap();
        for (int i = menus.size(); i > 0; i--) {
            Menu menu = menus.get(i - 1);
            if (null != menu.getParentId() && menu.getParentId().equals(id)) {
                Subject subject = SecurityUtils.getSubject();
                if(!Strings.isNullOrEmpty(menu.getPermission()) && subject.isPermitted(menu.getPermission())) {
                    menuMap.put("id", menu.getId());
                    menuMap.put("rule", menu.getRule());
                    menuMap.put("icon", menu.getIcon());
                    menuMap.put("name", menu.getName());
                    menuMap.put("href", menu.getHref());
                    menuMap.put("permission", menu.getPermission());
                    menuMap.put("children", buildTreeData(menu.getId(), menus));
                    break;
                }
            }
        }
        return menuMap;
    }

    private String getUrl(List<Map> maps) {
        for (Map<String, Object> map : maps) {
            if (map.get("children") != null && ((JSONArray) map.get("children")).size() > 0) {
                JSONArray jsonArray = (JSONArray) map.get("children");
                String s = JSONObject.toJSONString(jsonArray);
                List<Map> mm = JSONObject.parseObject(s, List.class);
                return getUrl(mm);
            } else {
                return map.get("href").toString();
            }
        }
        return null;
    }
}
